/*******************************************************************************
@copyright: 2025-2026, 汉威科技集团股份有限公司
@file:      PrivateProtocol.c
@version:   V1.0
@brief:     私有协议 
@warning:   无
@remarks:   1.私有协议版本号V1.00
            2.接收到数据需要先通过 n_PrivateUnpack 函数拆包后再使用ModbusRTU协议解析.
            3.ModbusRTU协议应答帧数据需要通过 n_PrivatePacket 函数封装后再发送.
            4.封包数据内存最小尺寸: 128 Bytes
            5.支持原位拆包/封包(原始数据内存地址与拆包/封包数据内存地址相同).
            6.文件编码类型UTF-8
 1.version: 1.0     author: MLF     date: 2025-05-10
   modification: 建立文档
*******************************************************************************/

/* Includes ------------------------------------------------------------------*/
#include "PrivateProtocol.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/

#define PRIVATE_FRAME_LEN_MIN  (uint8_t)(40U) /*!< 请求帧结构最小长度 */

#define  PrvPrt_Dst_DevNum            (0x00U)   /*!< 私有协议从机设备号 */
#define  PrvPrt_Src_DevNum            (0xFFU)   /*!< 私有协议主机设备号 */
#define  COMM_RESPONSE_TIME           (100U)    /*!< 时间期望          */        

#define  PRI_OFFSET_DST_ADDR          (0x00U)   /*!< 目的地址下标      */         
#define  PRI_OFFSET_SRC_ADDR          (0x01U)   /*!< 源地址下标        */           
#define  PRI_OFFSET_TIME              (0x02U)   /*!< 时间期望下标      */  
#define  PRI_OFFSET_SN1               (0x03U)   /*!< 序列号下标1       */
#define  PRI_OFFSET_SN2               (0x04U)   /*!< 序列号下标2       */
#define  PRI_OFFSET_SN3               (0x05U)   /*!< 序列号下标3       */
#define  PRI_OFFSET_SN4               (0x06U)   /*!< 序列号下标4       */
#define  PRI_OFFSET_PDU_LEN           (0x07U)   /*!< PDU长度下标       */
#define  PRI_OFFSET_DATA              (0x08U)   /*!< 数据起始下标      */
#define  PRI_PDU_LEN                  (0x0CU)   /*!< PDU固定格式长度   */

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/

//static uint32_t u32L_SN = 0U;

/* Private function prototypes -----------------------------------------------*/

/**
 * @brief  CRC32 校验算法
 * @note   多项式 0x4C11DB7
 * @param  acu8I_Data[]: 待校验数据
 * @param  u16I_Len:     待校验数据长度 
 * @retval 
 */
static uint32_t n_Crc32(const uint8_t acu8I_Data[], uint16_t u16I_Len);

/**
 * @brief  报文长度检查
 * @note   
 * @param  acu8I_Data[]:    报文数据
 * @param  u16I_Len:        报文长度
 * @param  u16I_DataLenMax: 数据包最大长度
 * @retval 1，正常
 */
static int32_t n_MsgLenCheck(const uint8_t acu8I_Data[], uint16_t u16I_Len, uint16_t u16I_DataLenMax);

/**
 * @brief  地址检查
 * @note   
 * @param  acu8I_Data[]: 报文数据
 * @param  u16I_Len:     报文长度
 * @retval 1，正常
 */
static int32_t n_AddrCheck(const uint8_t acu8I_Data[], uint16_t u16I_Len);

/**
 * @brief  时间期望检查
 * @note   
 * @param  acu8I_Data[]: 报文数据
 * @param  u16I_Len:     报文长度
 * @retval 1，正常 
 */
static int32_t n_ResponseTimeCheck(const uint8_t acu8I_Data[], uint16_t u16I_Len);

/**
 * @brief  PDU1与PDU2数据一致性检查
 * @note   
 * @param  acu8I_Data[]: 报文数据
 * @param  u16I_Len:     报文长度
 * @retval 1，正常 
 */
static int32_t n_ConsistencyCheck(const uint8_t acu8I_Data[], uint16_t u16I_Len);

/**
 * @brief  序列号检查
 * @note   
 * @param  acu8I_Data[]: 报文数据
 * @param  u16I_Len:     报文长度
 * @param  u32I_SN:      当前序列号
 * @retval 
 */
static int32_t n_SerialCheck(const uint8_t acu8I_Data[], uint16_t u16I_Len, uint32_t u32I_SN);

/**
 * @brief  报文内容检查
 * @note   
 * @param  acu8I_Data[]: 报文数据
 * @param  u16I_Len:     报文长度
 * @retval 1，正常 
 */
static int32_t n_PrvFrameCrc(const uint8_t acu8I_Data[], uint16_t u16I_Len);

/**
 * @brief  帧格式检查
 * @note   
 * @param  acu8I_Data[]:    报文数据
 * @param  u16I_Len:        报文长度
 * @param  u16I_DataLenMax: 数据包最大长度
 * @param  u32I_SN:         当前序列号
 * @param  pu16O_Num:       内层报文长度
 * @retval 1,格式正确
 */
static int32_t n_FrameCheck(const uint8_t acu8I_Data[], \
                            uint16_t u16I_Len,          \
                            uint16_t u16I_DataLenMax,   \
                            uint32_t u32I_SN,           \
                            uint16_t* pu16O_Num);                        

/* Public variables ----------------------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

#if 0
/**
 * @brief  CRC32 校验算法
 * @note   多项式 0x4C11DB7
 * @param  acu8I_Data[]: 待校验数据
 * @param  u16I_Len:     待校验数据长度 
 * @retval 
 */
static uint32_t n_Crc32(const uint8_t acu8I_Data[], uint16_t u16I_Len)
{
  static const uint32_t  acu32S_Table[256U] =
  {
    0x00000000U, 0x77073096U, 0xEE0E612CU, 0x990951BAU,0x076DC419U, 0x706AF48FU, 0xE963A535U, 0x9E6495A3U,
    0x0EDB8832U, 0x79DCB8A4U, 0xE0D5E91EU, 0x97D2D988U,0x09B64C2BU, 0x7EB17CBDU, 0xE7B82D07U, 0x90BF1D91U,
    0x1DB71064U, 0x6AB020F2U, 0xF3B97148U, 0x84BE41DEU,0x1ADAD47DU, 0x6DDDE4EBU, 0xF4D4B551U, 0x83D385C7U,
    0x136C9856U, 0x646BA8C0U, 0xFD62F97AU, 0x8A65C9ECU,0x14015C4FU, 0x63066CD9U, 0xFA0F3D63U, 0x8D080DF5U,
    0x3B6E20C8U, 0x4C69105EU, 0xD56041E4U, 0xA2677172U,0x3C03E4D1U, 0x4B04D447U, 0xD20D85FDU, 0xA50AB56BU,
    0x35B5A8FAU, 0x42B2986CU, 0xDBBBC9D6U, 0xACBCF940U,0x32D86CE3U, 0x45DF5C75U, 0xDCD60DCFU, 0xABD13D59U,
    0x26D930ACU, 0x51DE003AU, 0xC8D75180U, 0xBFD06116U,0x21B4F4B5U, 0x56B3C423U, 0xCFBA9599U, 0xB8BDA50FU,
    0x2802B89EU, 0x5F058808U, 0xC60CD9B2U, 0xB10BE924U,0x2F6F7C87U, 0x58684C11U, 0xC1611DABU, 0xB6662D3DU,
    0x76DC4190U, 0x01DB7106U, 0x98D220BCU, 0xEFD5102AU,0x71B18589U, 0x06B6B51FU, 0x9FBFE4A5U, 0xE8B8D433U,
    0x7807C9A2U, 0x0F00F934U, 0x9609A88EU, 0xE10E9818U,0x7F6A0DBBU, 0x086D3D2DU, 0x91646C97U, 0xE6635C01U,
    0x6B6B51F4U, 0x1C6C6162U, 0x856530D8U, 0xF262004EU,0x6C0695EDU, 0x1B01A57BU, 0x8208F4C1U, 0xF50FC457U,
    0x65B0D9C6U, 0x12B7E950U, 0x8BBEB8EAU, 0xFCB9887CU,0x62DD1DDFU, 0x15DA2D49U, 0x8CD37CF3U, 0xFBD44C65U,
    0x4DB26158U, 0x3AB551CEU, 0xA3BC0074U, 0xD4BB30E2U,0x4ADFA541U, 0x3DD895D7U, 0xA4D1C46DU, 0xD3D6F4FBU,
    0x4369E96AU, 0x346ED9FCU, 0xAD678846U, 0xDA60B8D0U,0x44042D73U, 0x33031DE5U, 0xAA0A4C5FU, 0xDD0D7CC9U,
    0x5005713CU, 0x270241AAU, 0xBE0B1010U, 0xC90C2086U,0x5768B525U, 0x206F85B3U, 0xB966D409U, 0xCE61E49FU,
    0x5EDEF90EU, 0x29D9C998U, 0xB0D09822U, 0xC7D7A8B4U,0x59B33D17U, 0x2EB40D81U, 0xB7BD5C3BU, 0xC0BA6CADU,
    0xEDB88320U, 0x9ABFB3B6U, 0x03B6E20CU, 0x74B1D29AU,0xEAD54739U, 0x9DD277AFU, 0x04DB2615U, 0x73DC1683U,
    0xE3630B12U, 0x94643B84U, 0x0D6D6A3EU, 0x7A6A5AA8U,0xE40ECF0BU, 0x9309FF9DU, 0x0A00AE27U, 0x7D079EB1U,
    0xF00F9344U, 0x8708A3D2U, 0x1E01F268U, 0x6906C2FEU,0xF762575DU, 0x806567CBU, 0x196C3671U, 0x6E6B06E7U,
    0xFED41B76U, 0x89D32BE0U, 0x10DA7A5AU, 0x67DD4ACCU,0xF9B9DF6FU, 0x8EBEEFF9U, 0x17B7BE43U, 0x60B08ED5U,
    0xD6D6A3E8U, 0xA1D1937EU, 0x38D8C2C4U, 0x4FDFF252U,0xD1BB67F1U, 0xA6BC5767U, 0x3FB506DDU, 0x48B2364BU,
    0xD80D2BDAU, 0xAF0A1B4CU, 0x36034AF6U, 0x41047A60U,0xDF60EFC3U, 0xA867DF55U, 0x316E8EEFU, 0x4669BE79U,
    0xCB61B38CU, 0xBC66831AU, 0x256FD2A0U, 0x5268E236U,0xCC0C7795U, 0xBB0B4703U, 0x220216B9U, 0x5505262FU,
    0xC5BA3BBEU, 0xB2BD0B28U, 0x2BB45A92U, 0x5CB36A04U,0xC2D7FFA7U, 0xB5D0CF31U, 0x2CD99E8BU, 0x5BDEAE1DU,
    0x9B64C2B0U, 0xEC63F226U, 0x756AA39CU, 0x026D930AU,0x9C0906A9U, 0xEB0E363FU, 0x72076785U, 0x05005713U,
    0x95BF4A82U, 0xE2B87A14U, 0x7BB12BAEU, 0x0CB61B38U,0x92D28E9BU, 0xE5D5BE0DU, 0x7CDCEFB7U, 0x0BDBDF21U,
    0x86D3D2D4U, 0xF1D4E242U, 0x68DDB3F8U, 0x1FDA836EU,0x81BE16CDU, 0xF6B9265BU, 0x6FB077E1U, 0x18B74777U,
    0x88085AE6U, 0xFF0F6A70U, 0x66063BCAU, 0x11010B5CU,0x8F659EFFU, 0xF862AE69U, 0x616BFFD3U, 0x166CCF45U,
    0xA00AE278U, 0xD70DD2EEU, 0x4E048354U, 0x3903B3C2U,0xA7672661U, 0xD06016F7U, 0x4969474DU, 0x3E6E77DBU,
    0xAED16A4AU, 0xD9D65ADCU, 0x40DF0B66U, 0x37D83BF0U,0xA9BCAE53U, 0xDEBB9EC5U, 0x47B2CF7FU, 0x30B5FFE9U,
    0xBDBDF21CU, 0xCABAC28AU, 0x53B39330U, 0x24B4A3A6U,0xBAD03605U, 0xCDD70693U, 0x54DE5729U, 0x23D967BFU,
    0xB3667A2EU, 0xC4614AB8U, 0x5D681B02U, 0x2A6F2B94U,0xB40BBE37U, 0xC30C8EA1U, 0x5A05DF1BU, 0x2D02EF8DU
  };
    
  uint8_t  u8T_Index  = 0U;
  uint32_t u32T_Value = 0xFFFFFFFFU;

  if((acu8I_Data == NULL) || (u16I_Len == 0U))
  {
    return 0xFFFFFFFFU;
  }  

  for(uint32_t i = 0U; i < u16I_Len; i++)  
  {
    /* 根据当前数据获取下标 */  
    u8T_Index  = (uint8_t)(u32T_Value ^ (uint32_t)acu8I_Data[i]);

    /* 根据下标查表计算CRC32 */    
    u32T_Value = (u32T_Value >> 8U) ^ acu32S_Table[u8T_Index];  
  }  
  
  /* 返回CRC32计算结果 */    
  return u32T_Value;  
}
#else
/**
 * @brief  CRC32 校验算法
 * @note   多项式 0x4C11DB7
 * @param  acu8I_Data[]: 待校验数据
 * @param  u16I_Len:     待校验数据长度 
 * @retval 
 */
static uint32_t n_Crc32(const uint8_t acu8I_Data[], uint16_t u16I_Len)
{
  uint32_t u32T_Value = 0xFFFFFFFFU;

  for(uint16_t i=0U; i<u16I_Len; i++)
  {
    u32T_Value ^= acu8I_Data[i];

    for(uint8_t j=0U; j<8U; j++)
    {
      if((u32T_Value & 0x00000001U) != 0U)
      {
        u32T_Value = (u32T_Value >> 1U) ^ 0xEDB88320U;
      }
      else 
      {
        u32T_Value >>= 1U;
      }
    }
  }

  return u32T_Value;
}

#endif

/**
 * @brief  报文长度检查
 * @note   
 * @param  acu8I_Data[]:    报文数据
 * @param  u16I_Len:        报文长度
 * @param  u16I_DataLenMax: 数据包最大长度
 * @retval 1，正常
 */
static int32_t n_MsgLenCheck(const uint8_t acu8I_Data[], \
                               uint16_t u16I_Len,          \
                               uint16_t u16I_DataLenMax)
{
  return ((acu8I_Data != NULL)                                 &&\
          (u16I_Len >= PRIVATE_FRAME_LEN_MIN)                  &&\
          (u16I_DataLenMax >= ((u16I_Len / 2U) - PRI_PDU_LEN)) &&\
          (acu8I_Data[PRI_OFFSET_PDU_LEN] == acu8I_Data[((u16I_Len / 2U) + PRI_OFFSET_PDU_LEN)]) &&\
          ((acu8I_Data[PRI_OFFSET_PDU_LEN] + acu8I_Data[((u16I_Len / 2U) + PRI_OFFSET_PDU_LEN)]) == u16I_Len));
}

/**
 * @brief  地址检查
 * @note   
 * @param  acu8I_Data[]: 报文数据
 * @param  u16I_Len:     报文长度
 * @retval 1，正常
 */
static int32_t n_AddrCheck(const uint8_t acu8I_Data[], uint16_t u16I_Len)
{
  /* PDU1目的设备号符合预期 
     PDU2目的设备号符合预期
     PDU1源设备号符合预期 
     PDU2源设备号符合预期 */
  return ((PrvPrt_Dst_DevNum == acu8I_Data[PRI_OFFSET_DST_ADDR]) &&\
          (PrvPrt_Dst_DevNum == acu8I_Data[((u16I_Len / 2U) + PRI_OFFSET_DST_ADDR)]) &&\
          (PrvPrt_Src_DevNum == acu8I_Data[PRI_OFFSET_SRC_ADDR]) &&\
          (PrvPrt_Src_DevNum == acu8I_Data[((u16I_Len / 2U) + PRI_OFFSET_SRC_ADDR)]));
}

/**
 * @brief  时间期望检查
 * @note   
 * @param  acu8I_Data[]: 报文数据
 * @param  u16I_Len:     报文长度
 * @retval 1，正常 
 */
static int32_t n_ResponseTimeCheck(const uint8_t acu8I_Data[], uint16_t u16I_Len)
{
  /* PDU1时间期望正常
     PDU2时间期望正常*/
  return ((COMM_RESPONSE_TIME == acu8I_Data[PRI_OFFSET_TIME]) &&\
          (COMM_RESPONSE_TIME == acu8I_Data[((u16I_Len / 2U) + PRI_OFFSET_TIME)]));
}

/**
 * @brief  PDU1与PDU2数据一致性检查
 * @note   
 * @param  acu8I_Data[]: 报文数据
 * @param  u16I_Len:     报文长度
 * @retval 1，正常 
 */
static int32_t n_ConsistencyCheck(const uint8_t acu8I_Data[], uint16_t u16I_Len)
{
  /* 依次检查两组PDU数据一致性只检查Modbus的数据 */
  for(uint16_t i=0U; i<(acu8I_Data[PRI_OFFSET_PDU_LEN]-12U); i++)
  {      
    if(0xFFU != acu8I_Data[(PRI_OFFSET_DATA + i)] +\
                acu8I_Data[(u16I_Len/2U) + (uint16_t)(PRI_OFFSET_DATA+i)])
    {
      /* 数据不一致 */
      return 0;
    }
  } 

  return 1;
}

/**
 * @brief  序列号检查
 * @note   
 * @param  acu8I_Data[]: 报文数据
 * @param  u16I_Len:     报文长度
 * @param  u32I_SN:      当前序列号
 * @retval 
 */
static int32_t n_SerialCheck(const uint8_t acu8I_Data[], uint16_t u16I_Len, uint32_t u32I_SN)
{
  uint32_t u32T_SN1 = 0U;
  uint32_t u32T_SN2 = 0U;

  /* 获取PDU1序列号 */
  u32T_SN1  = (uint32_t)acu8I_Data[PRI_OFFSET_SN1];
  u32T_SN1 += (uint32_t)acu8I_Data[PRI_OFFSET_SN2] << 8U;
  u32T_SN1 += (uint32_t)acu8I_Data[PRI_OFFSET_SN3] << 16U;
  u32T_SN1 += (uint32_t)acu8I_Data[PRI_OFFSET_SN4] << 24U;

  /* 获取PDU2序列号 */
  u32T_SN2  = (uint32_t)acu8I_Data[((u16I_Len/2U)+PRI_OFFSET_SN1)];
  u32T_SN2 += (uint32_t)acu8I_Data[((u16I_Len/2U)+PRI_OFFSET_SN2)] << 8U;
  u32T_SN2 += (uint32_t)acu8I_Data[((u16I_Len/2U)+PRI_OFFSET_SN3)] << 16U;
  u32T_SN2 += (uint32_t)acu8I_Data[((u16I_Len/2U)+PRI_OFFSET_SN4)] << 24U;

  /* 检查序列号 */    
  return ((u32I_SN == u32T_SN1) && (u32I_SN == (uint32_t)(~u32T_SN2)));
}

/**
 * @brief  报文内容检查
 * @note   
 * @param  acu8I_Data[]: 报文数据
 * @param  u16I_Len:     报文长度
 * @retval 1，正常 
 */
static int32_t n_PrvFrameCrc(const uint8_t acu8I_Data[], uint16_t u16I_Len)
{
  uint32_t u32T_Crc = 0U;
  
  /* 检查PDU1包接收CRC32值 */
  u32T_Crc  = (uint32_t)acu8I_Data[((u16I_Len/2U)-4U)];
  u32T_Crc += (uint32_t)acu8I_Data[((u16I_Len/2U)-3U)] << 8U;
  u32T_Crc += (uint32_t)acu8I_Data[((u16I_Len/2U)-2U)] << 16U;
  u32T_Crc += (uint32_t)acu8I_Data[((u16I_Len/2U)-1U)] << 24U;
  if(u32T_Crc == n_Crc32(acu8I_Data, ((uint16_t)((u16I_Len/2U) - 4U))))
  {
    /* 获取PDU2包接收CRC32值 */
    u32T_Crc  = (uint32_t)acu8I_Data[(u16I_Len - 4U)];
    u32T_Crc += (uint32_t)acu8I_Data[(u16I_Len - 3U)] << 8U;
    u32T_Crc += (uint32_t)acu8I_Data[(u16I_Len - 2U)] << 16U;
    u32T_Crc += (uint32_t)acu8I_Data[(u16I_Len - 1U)] << 24U;

    return (u32T_Crc == n_Crc32(&acu8I_Data[(u16I_Len/2U)], ((uint16_t)((u16I_Len / 2U) - 4U))));
  }

  return 0;
}

/**
 * @brief  帧格式检查
 * @note   
 * @param  acu8I_Data[]:    报文数据
 * @param  u16I_Len:        报文长度
 * @param  u16I_DataLenMax: 数据包最大长度
 * @param  u32I_SN:         当前序列号
 * @param  pu16O_Num:       内层报文长度
 * @retval 1,格式正确
 */
static int32_t n_FrameCheck(const uint8_t acu8I_Data[], \
                            uint16_t u16I_Len,          \
                            uint16_t u16I_DataLenMax,   \
                            uint32_t u32I_SN,           \
                            uint16_t* pu16O_Num)
{
  /* 参数出错 */
  if(pu16O_Num == NULL)
  {
    return 0;
  }

  /* 检查报文长度 */ 
  else if(0 == n_MsgLenCheck(acu8I_Data, u16I_Len, u16I_DataLenMax))
  {
    /* 长度错误 */
    return 0;
  }

  /* 检查设备号 */ 
  else if(0 == n_AddrCheck(acu8I_Data, u16I_Len))
  {
    /* 设备号传输错误 */
    return 0;
  }

  /* 检查时间期望 */ 
  else if(0 == n_ResponseTimeCheck(acu8I_Data, u16I_Len))
  {
    /* 时间期望错误 */
    return 0;
  }

  /* 依次检查两组PDU数据一致性,只检查Modbus的数据 */
  else if(0 == n_ConsistencyCheck(acu8I_Data, u16I_Len))
  {
    /* 数据错误 */
    return 0;
  }

  /* 检查序列号 */
  else if(0 == n_SerialCheck(acu8I_Data, u16I_Len, u32I_SN))
  {
    /* 序列号错误 */
    return 0;
  }

  /* 检查两组PDU数据的CRC是否正确 */
  else if(0 == n_PrvFrameCrc(acu8I_Data, u16I_Len))
  {
    /* CRC32校验错误，数据有误 */
    return 0;
  }
  
  /* 报文格式正确 */
  else
  {
    /* 获取数据包长度 */
    *pu16O_Num = (u16I_Len / 2U) - PRI_PDU_LEN;
  }

  return 1;
}

/**
 * @brief  私有协议封装
 * @note   
 * @param[in]   acu8I_Src[]:  原始数据
 * @param[in]   u16I_SrcNum:  原始数据个数 
 * @param[in]   u16I_DstSize: 存放封装数据的缓存大小
 * @param[out]  au8O_Dst[]:   封装后数据
 * @param[out]  pu16O_DstLen: 封装后数据个数
 * @retval 0: 封装失败
 *         1: 封装成功
 */                        
int32_t x_PrivatePacket(uint8_t const acu8I_Src[],  \
                        uint16_t      u16I_SrcNum,  \
                        uint16_t      u16I_DstSize, \
                        uint8_t       au8O_Dst[],   \
                        uint16_t*     pu16O_DstLen)
{
  uint32_t u32T_SN  = 0U; //u32L_SN; 
  uint32_t u32T_Crc = 0U;   
  uint16_t u16T_Len = 0U;

  /* 检查参数 */
  if((acu8I_Src == NULL) ||\
     (u16I_SrcNum == 0U) ||\
     (au8O_Dst  == NULL) ||\
     (pu16O_DstLen == NULL))
  {
    return 0;
  }

  /* 缓存不足 */
  if(u16I_DstSize < ((u16I_SrcNum + PRI_PDU_LEN) * 2U))
  {
    return 0;
  }

  /* 获取单个PDU长度 */
  u16T_Len = (u16I_SrcNum + PRI_OFFSET_DATA) + 4U;

  /* 将Modbus数据同时存入PDU1、PDU2数据包 */   
  //for(uint16_t i=0U; i<u16I_SrcNum; i++)
  //{
    /* PDU1 */
  //  au8O_Dst[(PRI_OFFSET_DATA+i)] = acu8I_Src[i];

    /* PDU2 */
  //  au8O_Dst[((u16T_Len+PRI_OFFSET_DATA)+i)] = (uint8_t)(~acu8I_Src[i]);
  //}
  for(uint16_t i=u16I_SrcNum; i>0U; i--)
  {
    /* PDU1 */
    au8O_Dst[(PRI_OFFSET_DATA+(i-1U))] = acu8I_Src[(i-1U)];

    /* PDU2 */
    au8O_Dst[((u16T_Len+PRI_OFFSET_DATA)+(i-1U))] = (uint8_t)(~acu8I_Src[(i-1U)]);
  }

  /********************打包PDU1数据包************************/ 
  /* 载入目的设备号 */
  au8O_Dst[PRI_OFFSET_DST_ADDR] = PrvPrt_Src_DevNum; 

  /* 载入源设备号 */ 
  au8O_Dst[PRI_OFFSET_SRC_ADDR] = PrvPrt_Dst_DevNum; 

  /* 载入预期时间 */
  au8O_Dst[PRI_OFFSET_TIME] = COMM_RESPONSE_TIME; 

  /* 载入序列号 */
  au8O_Dst[PRI_OFFSET_SN4] = (uint8_t)(u32T_SN >> 0U);
  au8O_Dst[PRI_OFFSET_SN3] = (uint8_t)(u32T_SN >> 8U);
  au8O_Dst[PRI_OFFSET_SN2] = (uint8_t)(u32T_SN >> 16U);
  au8O_Dst[PRI_OFFSET_SN1] = (uint8_t)(u32T_SN >> 24U);

  /* 载入PDU1报文长度 */
  au8O_Dst[PRI_OFFSET_PDU_LEN] = (uint8_t)u16T_Len;    

  /* 载入PDU1 CRC32校验值 */
  u32T_Crc = n_Crc32(au8O_Dst, (u16T_Len - 4U)); 
  au8O_Dst[(u16T_Len-4U)] = (uint8_t)(u32T_Crc >> 0U);
  au8O_Dst[(u16T_Len-3U)] = (uint8_t)(u32T_Crc >> 8U);
  au8O_Dst[(u16T_Len-2U)] = (uint8_t)(u32T_Crc >> 16U);
  au8O_Dst[(u16T_Len-1U)] = (uint8_t)(u32T_Crc >> 24U);

  /********************打包PDU2数据包************************/  
  /* 载入目的设备号 */
  au8O_Dst[(u16T_Len + PRI_OFFSET_DST_ADDR)] = PrvPrt_Src_DevNum; 

  /* 载入源设备号 */  
  au8O_Dst[(u16T_Len + PRI_OFFSET_SRC_ADDR)] = PrvPrt_Dst_DevNum; 

  /* 载入预期时间 */ 
  au8O_Dst[(u16T_Len + PRI_OFFSET_TIME)] = COMM_RESPONSE_TIME;  

  /* 获取PDU2序列号 */  
  u32T_SN = ~u32T_SN;

  /* 载入序列号 */
  au8O_Dst[(u16T_Len + PRI_OFFSET_SN4)] = (uint8_t)(u32T_SN >> 0U);
  au8O_Dst[(u16T_Len + PRI_OFFSET_SN3)] = (uint8_t)(u32T_SN >> 8U);
  au8O_Dst[(u16T_Len + PRI_OFFSET_SN2)] = (uint8_t)(u32T_SN >> 16U);
  au8O_Dst[(u16T_Len + PRI_OFFSET_SN1)] = (uint8_t)(u32T_SN >> 24U);

  /* 载入PDU2报文长度 */  
  au8O_Dst[(u16T_Len + PRI_OFFSET_PDU_LEN)] = (uint8_t)u16T_Len;   
  
  /* 载入PDU2 CRC32校验值 */ 
  u32T_Crc = n_Crc32(&au8O_Dst[u16T_Len], (u16T_Len - 4U));
  au8O_Dst[((u16T_Len*2U)-4U)] = (uint8_t)(u32T_Crc >> 0U); 
  au8O_Dst[((u16T_Len*2U)-3U)] = (uint8_t)(u32T_Crc >> 8U);
  au8O_Dst[((u16T_Len*2U)-2U)] = (uint8_t)(u32T_Crc >> 16U);
  au8O_Dst[((u16T_Len*2U)-1U)] = (uint8_t)(u32T_Crc >> 24U);

  /* 获取发送总长度 */
  u16T_Len = (u16I_SrcNum + PRI_PDU_LEN) * 2U;
  *pu16O_DstLen = u16T_Len;
  return 1;
}

/**
 * @brief  私有协议拆包
 * @note   
 * @param[in]   acu8I_Src[]:  原始数据包
 * @param[in]   u16I_SrcLen:  原始数据包长度
 * @param[in]   u16I_DstSize: 存放拆包数据的缓存大小
 * @param[out]  au8O_Dst[]:   拆包后的数据包
 * @param[out]  pu16O_DstLen: 拆包后的数据包长度
 * @retval 0: 拆包失败
 *         1: 拆包成功
 */
int32_t x_PrivateUnpack(uint8_t const acu8I_Src[],  \
                        uint16_t      u16I_SrcNum,  \
                        uint16_t      u16I_DstSize, \
                        uint8_t       au8O_Dst[],   \
                        uint16_t*     pu16O_DstLen)
{
  uint16_t u16T_Num = 0U;

  /* 检查参数 */
  if((acu8I_Src    == NULL) ||\
     (u16I_SrcNum    == 0U) ||\
     (au8O_Dst     == NULL) ||\
     (pu16O_DstLen == NULL))
  {
    return 0;
  }

  /* 报文格式出错 */
  //if(1 != n_FrameCheck(acu8I_Src, u16I_SrcNum, u16I_DstSize, u32L_SN, &u16T_Num))
  if(1 != n_FrameCheck(acu8I_Src, u16I_SrcNum, u16I_DstSize, 0U, &u16T_Num))
  {
    return 0;
  }

  /* 拆包数据 */
  for(uint16_t i=0U; i<u16T_Num; i++)
  {
    au8O_Dst[i] = acu8I_Src[(uint16_t)PRI_OFFSET_DATA + i];
  }
  *pu16O_DstLen = u16T_Num;
  return 1;
}

/*******************************************************************************
                                   END FILE
*******************************************************************************/
